/**     
 * @Title: ConvertUtil.java   
 * @Package me.xxy.mq   
 * @Description: TODO
 * @author weiwei 
 * @date 2018年5月30日 下午4:38:57   
 * @version V1.0     
 */
package me.xxy.mq.core;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: ConvertUtil
 * @Description: TODO
 * @author weiwei
 * @date 2018年5月30日 下午4:38:57
 * 
 */
public class ConvertUtil {

	private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();

	@SuppressWarnings("unchecked")
	private static <T> Schema<T> getSchema(Class<T> clazz) {
		Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
		if (null == schema) {
			schema = RuntimeSchema.createFrom(clazz);
			if (null != schema) {
				cachedSchema.put(clazz, schema);
			}
		}
		return schema;
	}

	@SuppressWarnings("unchecked")
	public static <T> byte[] serialize(T obj) {
		Class<T> clazz = (Class<T>) obj.getClass();
		LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
		try {
			Schema<T> schema = getSchema(clazz);
			return ProtobufIOUtil.toByteArray(obj, schema, buffer);
		} catch (Exception e) {
			throw new IllegalStateException(e.getMessage(), e);
		} finally {
			buffer.clear();
		}
	}

	public static <T> T unserialize(byte[] data, Class<T> clazz) {
		try {
			T message = clazz.newInstance();
			Schema<T> schema = getSchema(clazz);
			ProtobufIOUtil.mergeFrom(data, message, schema);
			return message;
		} catch (Exception e) {
			throw new IllegalStateException(e.getMessage(), e);
		}
	}
}
